package com.dmz.insclient.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.HexUtil;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.io.BufferedInputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @author lee
 */
@Slf4j
public class RsaUtil {

    /**
     * 获取公钥
     *
     * @return
     * @throws Exception
     */
    public static PublicKey GeneratePublicKey(String keyType) throws Exception {
        BufferedInputStream fin;
        try {
            String keyLocation = EnvConfig.getProperty("key.save.path");
            fin = FileUtil.getInputStream(keyLocation + "/publicSB/public" + keyType + ".cer");
            byte[] encodedpubkey = new byte[fin.available()];
            fin.read(encodedpubkey);
            fin.close();
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(
                    encodedpubkey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
            return pubKey;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;

        }
    }

    /**
     * 获取公钥-银行端
     *
     * @return
     * @throws Exception
     */
    public static PublicKey GeneratePublicKeyYH(String keyType) throws Exception {
        BufferedInputStream fin;
        try {
            String keyLocation = EnvConfig.getProperty("key.save.path");
            fin = FileUtil.getInputStream(keyLocation + "/publicYH/public" + keyType + ".cer");
            byte[] encodedpubkey = new byte[fin.available()];
            fin.read(encodedpubkey);
            fin.close();
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(
                    encodedpubkey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
            return pubKey;
        } catch (Exception e) {
            log.error(e.toString());
            throw e;
        }
    }


    /**
     * 获取私钥-银行
     *
     * @return
     * @throws Exception
     */
    public static PrivateKey GeneratePrivateKeyYH(String keyType) throws Exception {
        BufferedInputStream fin;
        try {
            String keyLocation = EnvConfig.getProperty("key.save.path");
            File keyFile = FileUtil.newFile(keyLocation + "/privateYH/private" + keyType + ".key");
            fin = keyFile.exists() ? FileUtil.getInputStream(keyFile) : null;
            byte[] encodedprikey = new byte[fin.available()];
            fin.read(encodedprikey);
            fin.close();
            PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
                    encodedprikey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyFactory.generatePrivate(priKeySpec);
            return priKey;
        } catch (Exception e) {
            log.error(e.toString());
            throw e;
        }
    }

    /**
     * 公钥加密
     *
     * @param data      加密秘钥，待加密的秘钥
     * @param publicKey 社保的公钥
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, RSAPublicKey publicKey)
            throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] ciByte = cipher.doFinal(data.getBytes());
        return HexUtil.encodeHexStr(ciByte);

    }

    /**
     * 私钥解密
     *
     * @param data       加密秘钥，待解密的秘钥
     * @param privateKey 银行的私钥
     * @return
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data,
                                             RSAPrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] enCrypted = HexUtil.decodeHex(data.toCharArray());
        return new String(cipher.doFinal(enCrypted));
    }

    /**
     * 签名
     *
     * @param data 待签名的内容 用银行的私钥
     * @return
     * @throws Exception
     */
    public static String genValiInfo(byte[] data, String keyType) throws Exception {
        try {
            PrivateKey privateKey = GeneratePrivateKeyYH(keyType);
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initSign(privateKey);
            sig.update(data);
            return HexUtil.encodeHexStr(sig.sign());
        } catch (Exception e) {
            log.error(e.toString());
            throw e;
        }
    }

    /**
     * 验签
     *
     * @param content 待签名的内容 用社保的公钥
     * @param data    签名得到的字符串
     * @return
     * @throws Exception
     */
    public static boolean validate(String content, byte[] data, String keyType) throws Exception {
        try {
            PublicKey publicKey = GeneratePublicKey(keyType);
            //		PublicKey publicKey = GeneratePublicKeyYH(keyType);
            Signature sig = Signature.getInstance("SHA1withRSA");
            sig.initVerify(publicKey);
            sig.update(content.getBytes(StandardCharsets.UTF_8));
            return sig.verify(data);
        } catch (Exception e) {
            log.error(e.toString());
            throw e;
        }
    }
}
